home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Information / Mac Programming Secrets 1.0.1 / Chapter 07 / ZoomRect.c < prev    next >
C/C++ Source or Header  |  1992-05-19  |  5KB  |  141 lines

  1. #include "ZoomRect.h"
  2. #include "Math.h"            // For pow().
  3.  
  4. /*******************************************************************************
  5.  
  6.     ZoomRect
  7.  
  8.     Draws a series of rectangles that give the appearance of a source rectangle
  9.     being transformed into a destination rectangle. Drawing takes place in a
  10.     GrafPort that covers all monitors.
  11.  
  12.     The basic idea is this: a transformation in progress can be said to be
  13.     partially complete. The amount by which the transformation is complete can
  14.     be expressed as a percentage. Given this percentage, we can calculate the
  15.     rectangle that needs to be drawn. For example, if we were animating the
  16.     transformation of rectangle (0, 0, 32, 32) into (40, 4, 300, 500),
  17.     then rectangle drawn at the 50% point would be (20, 2, 166, 266).
  18.  
  19.     Using mathematical formulas determined by the mode parameter, 12
  20.     intermediate percentages are determined, and the rectangles corresponding
  21.     to these percentages are generated. These 12 rectangles are then drawn
  22.     four at a time. First, rectangles 1, 2, 3, and 4 are drawn. Then,
  23.     rectangle 1 is erased and rectangle 5 is drawn. This process continues
  24.     until all 12 rectangles have had their turn.
  25.  
  26.     The caller can choose one of three different formulas to determine the
  27.     percentages used to generate the rectangles.
  28.  
  29.         kZoomOut -    This effect can be used for zooming a small rectangle into
  30.                     a larger one. Each percentage is 7/5 as large as the
  31.                     previous percentage. The final generated value is 100%.
  32.                     This gives the effect of starting out slowly and finishing
  33.                     up quickly. It can also be percieved as seeing a rectangle
  34.                     move forward from a far distance.
  35.  
  36.         kZoomIn  -    This effect can be used for zooming a large rectangle into
  37.                     a smaller one. Each percentage is 5/7 as large as the
  38.                     previous percentage. The first value generated is 100%,
  39.                     and subsequent values are smaller. Because the values are
  40.                     generated backwards from the way we’d like them, we also
  41.                     swap the source and destination rectangles to get the
  42.                     desired effect, which is to start out quickly, and finish
  43.                     up slowly. It can also be percieved as a rectangle moving
  44.                     off into the distance.
  45.  
  46.         kLinear  -    This effect can be used for moving a rectangle from one
  47.                     place to another without changing its size. Each percentage
  48.                     is evenly spaced from 0% to 100%. This gives a nice even,
  49.                     measured effect. It gives the impression of a rectangle
  50.                     moving in a single plane, rather than moving into the
  51.                     distance or vice-versa.
  52.  
  53. *******************************************************************************/
  54. void ZoomRect(Rect source, Rect dest, short mode) {
  55.  
  56.     GrafPtr        oldPort;
  57.     GrafPort    zoomPort;
  58.     Rect        tempRect[4];
  59.     Fixed        deltas[4];
  60.     int            numberOfSteps;
  61.     Fixed        percentComplete;
  62.     Fixed        acceleration;
  63.     long        dasTicks;
  64.  
  65.     GetPort(&oldPort);
  66.     OpenPort(&zoomPort);
  67.     SetPort(&zoomPort);
  68.     CopyRgn(GetGrayRgn(), zoomPort.visRgn);
  69.  
  70.     PenPat(qd.gray);
  71.     PenMode(patXor);
  72.  
  73.     numberOfSteps = 12;
  74.  
  75.     switch (mode) {
  76.         case kZoomOut:
  77.             acceleration = FixRatio(7, 5);
  78.             percentComplete = FixRatio(32767/(pow((7./5.), numberOfSteps)), 32767);
  79.             break;
  80.         case kZoomIn:
  81.             tempRect[0] = source;
  82.             source = dest;
  83.             dest = tempRect[0];
  84.             acceleration = FixRatio(5, 7);
  85.             percentComplete = 65536;    // shorthand for FixRatio(1, 1), or 100%
  86.             break;
  87.         case kLinear:
  88.             acceleration = FixRatio(1, numberOfSteps);
  89.             percentComplete = acceleration;
  90.             break;
  91.     }
  92.  
  93.     deltas[0] = FixRatio(dest.top - source.top, 1);
  94.     deltas[1] = FixRatio(dest.left - source.left, 1);
  95.     deltas[2] = FixRatio(dest.bottom - source.bottom, 1);
  96.     deltas[3] = FixRatio(dest.right - source.right, 1);
  97.  
  98.     SetRect(&tempRect[1], 0, 0, 0, 0);
  99.     tempRect[3] = tempRect[2] = tempRect[1];
  100.  
  101.     dasTicks = TickCount() + 1;
  102.     do {
  103.         tempRect[0] = source;
  104.         tempRect[0].top        += FixRound(FixMul(deltas[0], percentComplete));
  105.         tempRect[0].left    += FixRound(FixMul(deltas[1], percentComplete));
  106.         tempRect[0].bottom    += FixRound(FixMul(deltas[2], percentComplete));
  107.         tempRect[0].right    += FixRound(FixMul(deltas[3], percentComplete));
  108.  
  109.         FrameRect(&tempRect[0]);            // Draw the latest rectangle
  110.  
  111.         while (dasTicks >= TickCount()) ;    // Just wait for counter to change
  112.         dasTicks = TickCount() + 1;
  113.  
  114.         if (!EmptyRect(&tempRect[3]))
  115.             FrameRect(&tempRect[3]);        // Erase any guy who’s been around
  116.                                             // too long.
  117.  
  118.         tempRect[3] = tempRect[2];
  119.         tempRect[2] = tempRect[1];
  120.         tempRect[1] = tempRect[0];
  121.  
  122.         switch (mode) {
  123.             case kZoomOut:
  124.             case kZoomIn:
  125.                 percentComplete = FixMul(percentComplete, acceleration);
  126.                 break;
  127.             case kLinear:
  128.                 percentComplete += acceleration;
  129.                 break;
  130.         }
  131.  
  132.     } while (--numberOfSteps);
  133.  
  134.     FrameRect(&tempRect[3]);                // Erase anything left on screen
  135.     FrameRect(&tempRect[2]);
  136.     FrameRect(&tempRect[1]);
  137.  
  138.     SetPort(oldPort);
  139.     ClosePort(&zoomPort);
  140. }
  141.